在現代桌面應用開發中,自動更新機制已成為必備功能。它不僅能確保使用者始終使用最新版本,還能及時修復安全漏洞和錯誤。Tauri 2.0 提供了完整的自動更新解決方案,讓開發者能夠輕鬆為 Windows 應用程式加入專業級的更新功能。
Tauri 的自動更新機制採用了安全且高效的設計:
首先在 tauri.conf.json 中啟用更新功能:
{
  "bundle": {
    "createUpdaterArtifacts": true
  },
  "plugins": {
    "updater": {
      "pubkey": "CONTENT FROM PUBLICKEY.PEM",
      "endpoints": [
        "https://releases.myapp.com/{{target}}/{{arch}}/{{current_version}}",
        // or a static github json file
        "https://github.com/user/repo/releases/latest/download/latest.json"
      ]
    }
  }
}
- 這邊的
pubkey就是數位簽章時使用的公鑰 (public key) ,這部分下一個段落會進行說明
endpoints就是指伺服器端,用來提供 JSON 檔。
伺服器端需要提供一個 JSON 檔案,包含最新版本資訊:
{
  "version": "",
  "notes": "",
  "pub_date": "",
  "platforms": {
    "linux-x86_64": {
      "signature": "",
      "url": ""
    },
    "windows-x86_64": {
      "signature": "",
      "url": ""
    },
    "darwin-x86_64": {
      "signature": "",
      "url": ""
    }
  }
}
Updater 相關設定如果有完成的話,在打包後會有額外的
.sig檔案產生,就是上面 JSON 內的signature。
自動更新最重要的一環就是「安全性」。我們必須確保使用者下載的更新檔確實是由我們發佈的,而不是被惡意竄改的版本。Updater 透過非對稱加密簽章來保證這一點。
執行流程如下:
這個金鑰設定是強制性的,若沒有設定,Updater 將無法運作。
Tauri CLI 有提供工具來產生數位簽章用的公鑰、私鑰。指令如下:
npm run tauri signer generate

通常都是在啟動時,直接在後端 Rust 進行版本檢查與更新:
use tauri_plugin_updater::UpdaterExt;
pub fn run() {
  tauri::Builder::default()
    .setup(|app| {
      let handle = app.handle().clone();
      tauri::async_runtime::spawn(async move {
        update(handle).await.unwrap();
      });
      Ok(())
    })
    .run(tauri::generate_context!())
    .unwrap();
}
async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> {
  if let Some(update) = app.updater()?.check().await? {
    let mut downloaded = 0;
    // alternatively we could also call update.download() and update.install() separately
    update
      .download_and_install(
        |chunk_length, content_length| {
          downloaded += chunk_length;
          println!("downloaded {downloaded} from {content_length:?}");
        },
        || {
          println!("download finished");
        },
      )
      .await?;
    println!("update installed");
    app.restart();
  }
  Ok(())
}
也可以在前端 JS 實作:
import { check } from '@tauri-apps/plugin-updater';
import { relaunch } from '@tauri-apps/plugin-process';
const update = await check();
if (update) {
  console.log(
    `found update ${update.version} from ${update.date} with notes ${update.body}`
  );
  let downloaded = 0;
  let contentLength = 0;
  // alternatively we could also call update.download() and update.install() separately
  await update.downloadAndInstall((event) => {
    switch (event.event) {
      case 'Started':
        contentLength = event.data.contentLength;
        console.log(`started downloading ${event.data.contentLength} bytes`);
        break;
      case 'Progress':
        downloaded += event.data.chunkLength;
        console.log(`downloaded ${downloaded} from ${contentLength}`);
        break;
      case 'Finished':
        console.log('download finished');
        break;
    }
  });
  console.log('update installed');
  await relaunch();
}
Tauri 的更新機制內建多重安全保護:
通過實作自動更新功能,你的 Tauri 應用將擁有更專業的使用者體驗,同時確保安全性和可維護性。這項功能不僅提升了應用的競爭力,更體現了對使用者負責的開發態度。